#ifndef TSD__TEST_SELF_DEBUG_H
#define TSD__TEST_SELF_DEBUG_H

#include <stdint.h>

#define defineLocals(_type, _name, _value, _arrayValues...) \
_type _name = _value; \
_type *_name ## Pointer __attribute__((unused)) = &_name; \
_type &_name ## Reference __attribute__((unused)) = _name; \
_type _name ## Array[8] = _arrayValues; \
_type *_name ## ArrayPointer __attribute__((unused)) = _name ## Array; \
_type (&_name ## ArrayReference)[8] __attribute__((unused)) = _name ## Array; \
_type _name ## 2dArray[4][8] = {_arrayValues, _arrayValues}; \
_type (*_name ## 2dArrayPointer)[8] __attribute__((unused)) = _name ## 2dArray; \
_type (&_name ## 2dArrayReference)[4][8] __attribute__((unused)) = _name ## 2dArray; \
_type _name ## 3dArray[2][4][8] = {{_arrayValues, _arrayValues}}; \
_type (*_name ## 3dArrayPointer)[4][8] __attribute__((unused)) = _name ## 3dArray; \
_type (&_name ## 3dArrayReference)[2][4][8] __attribute__((unused)) = _name ## 3dArray;

#define declareStaticMembers(_type, _name) \
static _type _name ## _; \
static _type *_name ## Pointer_; \
static _type &_name ## Reference_; \
static _type _name ## Array_[8]; \
static _type *_name ## ArrayPointer_; \
static _type (&_name ## ArrayReference_)[8]; \
static _type _name ## 2dArray_[4][8]; \
static _type (*_name ## 2dArrayPointer_)[8]; \
static _type (&_name ## 2dArrayReference_)[4][8]; \
static _type _name ## 3dArray_[2][4][8]; \
static _type (*_name ## 3dArrayPointer_)[4][8]; \
static _type (&_name ## 3dArrayReference_)[2][4][8];

#define defineStaticMembers(_type, _class, _name, _value, _arrayValues...) \
_type _class::_name ## _ = _value; \
_type *_class::_name ## Pointer_ __attribute__((unused)) = &_name ## _; \
_type &_class::_name ## Reference_ __attribute__((unused)) = _name ## _; \
_type _class::_name ## Array_[8] = _arrayValues; \
_type *_class::_name ## ArrayPointer_ __attribute__((unused)) = _name ## Array_; \
_type (&_class::_name ## ArrayReference_)[8] __attribute__((unused)) = _name ## Array_; \
_type _class::_name ## 2dArray_[4][8] = {_arrayValues, _arrayValues}; \
_type (*_class::_name ## 2dArrayPointer_)[8] __attribute__((unused)) = _name ## 2dArray_; \
_type (&_class::_name ## 2dArrayReference_)[4][8] __attribute__((unused)) = _name ## 2dArray_; \
_type _class::_name ## 3dArray_[2][4][8] = {{_arrayValues, _arrayValues}}; \
_type (*_class::_name ## 3dArrayPointer_)[4][8] __attribute__((unused)) = _name ## 3dArray_; \
_type (&_class::_name ## 3dArrayReference_)[2][4][8] __attribute__((unused)) = _name ## 3dArray_;

#define declareMembers(_type, _name) \
_type _name ## _; \
_type *_name ## Pointer_; \
_type &_name ## Reference_; \
_type _name ## Array_[8]; \
_type *_name ## ArrayPointer_; \
_type (&_name ## ArrayReference_)[8]; \
_type _name ## 2dArray_[4][8]; \
_type (*_name ## 2dArrayPointer_)[8]; \
_type (&_name ## 2dArrayReference_)[4][8]; \
_type _name ## 3dArray_[2][4][8]; \
_type (*_name ## 3dArrayPointer_)[4][8]; \
_type (&_name ## 3dArrayReference_)[2][4][8];

#define constructMembers(_name, _value, _arrayValue0, _arrayValue1, _arrayValue2, _arrayValue3) \
_name ## _(_value), \
_name ## Pointer_(&_name ## _), \
_name ## Reference_(_name ## _), \
_name ## Array_(), \
_name ## ArrayPointer_(_name ## Array_), \
_name ## ArrayReference_(_name ## Array_), \
_name ## 2dArray_(), \
_name ## 2dArrayPointer_(_name ## 2dArray_), \
_name ## 2dArrayReference_(_name ## 2dArray_), \
_name ## 3dArray_(), \
_name ## 3dArrayPointer_(_name ## 3dArray_), \
_name ## 3dArrayReference_(_name ## 3dArray_) { \
    _name ## Array_[0] = _arrayValue0; \
    _name ## Array_[1] = _arrayValue1; \
    _name ## Array_[2] = _arrayValue2; \
    _name ## Array_[3] = _arrayValue3; \
    _name ## 2dArray_[0][0] = _arrayValue0; \
    _name ## 2dArray_[0][1] = _arrayValue1; \
    _name ## 2dArray_[0][2] = _arrayValue2; \
    _name ## 2dArray_[0][3] = _arrayValue3; \
    _name ## 2dArray_[1][0] = _arrayValue0; \
    _name ## 2dArray_[1][1] = _arrayValue1; \
    _name ## 2dArray_[1][2] = _arrayValue2; \
    _name ## 2dArray_[1][3] = _arrayValue3; \
    _name ## 3dArray_[0][0][0] = _arrayValue0; \
    _name ## 3dArray_[0][0][1] = _arrayValue1; \
    _name ## 3dArray_[0][0][2] = _arrayValue2; \
    _name ## 3dArray_[0][0][3] = _arrayValue3; \
    _name ## 3dArray_[0][1][0] = _arrayValue0; \
    _name ## 3dArray_[0][1][1] = _arrayValue1; \
    _name ## 3dArray_[0][1][2] = _arrayValue2; \
    _name ## 3dArray_[0][1][3] = _arrayValue3; \
}

namespace exe {

enum E {
	ONE = -1,
	TWO = -2,
	THREE = 3,
	FOUR = 4
};

union U {
	int32_t sInt32_;
	uint32_t uInt32_;
	E e_;
};

struct S {
public:
	declareStaticMembers(signed char, sChr)
public:
	bool bitBoolean_:7;
public:
	declareMembers(unsigned char, uChr)
public:
	S()
			: bitBoolean_(false),
	constructMembers(uChr, '1', '1', '2', '3', '4')
};

defineStaticMembers(signed char, S, sChr, -1, { -1, -2, 3, 4 })

class C : private S {
public:
	declareStaticMembers(signed int, sInt)
public:
	signed char bitSChr_:7;
	unsigned char bitUChr_:8;
public:
	declareMembers(unsigned int, uInt)
public:
	C()
			: S(),
			  bitSChr_(-1),
			  bitUChr_('1'),
	constructMembers(uInt, 1, 1, 2, 3, 4)
};

defineStaticMembers(signed int, C, sInt, -1, { -1, -2, 3, 4 })

template<typename _T>
class T {
public:
	_T t_;
public:
	declareStaticMembers(float, sFloat)
public:
	signed int bitSInt_:7;
	unsigned int bitUInt_:32;
public:
	declareMembers(double, sDouble)
public:
	T()
			: t_(),
			  bitSInt_(-1),
			  bitUInt_(1),
	constructMembers(sDouble, -0.1d, -0.1d, -0.2d, 0.3d, 0.4d)
};

defineStaticMembers(template<typename _T> float, T<_T>, sFloat, -0.1f, { -0.1f, -0.2f, 0.3f, 0.4f })

}

#endif // TSD__TEST_SELF_DEBUG_H
